package it.mainella.phone_state.receiver

import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
import android.media.MediaRecorder
import android.os.Build
import android.telephony.TelephonyManager
import io.flutter.util.PathUtils
import it.mainella.phone_state.utils.PhoneStateStatus
import java.io.File
import java.io.IOException
import java.util.*

open class PhoneStateReceiver : BroadcastReceiver() {
    val TAG = "Phone_State_Receiver"
    var status: PhoneStateStatus = PhoneStateStatus.NOTHING;
    override fun onReceive(context: Context, intent: Intent?) {
        try {
            status = when (intent?.getStringExtra(TelephonyManager.EXTRA_STATE)) {
                TelephonyManager.EXTRA_STATE_RINGING -> PhoneStateStatus.CALL_INCOMING
                TelephonyManager.EXTRA_STATE_OFFHOOK -> PhoneStateStatus.CALL_STARTED
                TelephonyManager.EXTRA_STATE_IDLE -> PhoneStateStatus.CALL_ENDED
                else -> PhoneStateStatus.NOTHING
            }
            android.util.Log.i(TAG, "onReceive: ")
            if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.P){
                android.util.Log.i(TAG, "onReceive: xxx")
                if (lastState == status) {
                    //No change, debounce extras
                    return
                }
                if(status==PhoneStateStatus.CALL_INCOMING){
                    isIncoming = true
                }
                if(status == PhoneStateStatus.CALL_STARTED){
                    if (lastState != PhoneStateStatus.CALL_INCOMING) {
                        isIncoming = false
                        callStartTime = Date()
                        startRecord(context, callStartTime)
                    } else {
                        isIncoming = true
                    }
                }
                if(status == PhoneStateStatus.CALL_ENDED){
                    if (lastState == PhoneStateStatus.CALL_INCOMING) {
                        //Ring but no pickup-  a miss
                        //onMissedCall(context, savedNumber, callStartTime)
                    } else if (isIncoming) {
                        //onIncomingCallEnded(context, savedNumber, callStartTime, Date())
                    } else {
                        stopRecord(context, callStartTime, Date())
                    }
                }
            }

        } catch (e: Exception) {
            e.printStackTrace()
        }
    }
    private fun startRecord(context: Context, start: Date) {
        try {
            val isSaveFile = true
            // is save file?
            if (!isSaveFile) {
                return
            }

            if (isRecordStarted) {
                try {
                    recorder?.stop()  // stop the recording
                } catch (e: RuntimeException) {
                    // RuntimeException is thrown when stop() is called immediately after start().
                    // In this case the output file is not properly constructed ans should be deleted.
                    audioFile?.delete()
                }

                releaseMediaRecorder()
                isRecordStarted = false
            } else {
                if (prepareAudioRecorder(context, start)) {
                    recorder!!.start()
                    isRecordStarted = true
                } else {
                    releaseMediaRecorder()
                }
            }
        } catch (e: IllegalStateException) {
            e.printStackTrace()
            releaseMediaRecorder()
        } catch (e: RuntimeException) {
            e.printStackTrace()
            releaseMediaRecorder()
        } catch (e: Exception) {
            e.printStackTrace()
            releaseMediaRecorder()
        }
    }

    private fun stopRecord(context: Context, start: Date,end:Date) {
        try {
            if (recorder != null && isRecordStarted) {
                releaseMediaRecorder()
                isRecordStarted = false
            }
        } catch (e: Exception) {
            releaseMediaRecorder()
            e.printStackTrace()
        }
    }

    private fun prepareAudioRecorder(context: Context,start:Date): Boolean {
        try {
            var fileName = "record"
            val dirPath = PathUtils.getFilesDir(context);
            val dirName = "Record"
//            val showSeed =false
//            val showPhoneNumber =false
            val outputFormat = MediaRecorder.OutputFormat.MPEG_4
            var audioSource= MediaRecorder.AudioSource.VOICE_COMMUNICATION
            if(Build.VERSION.SDK_INT == 23 ){
                audioSource = MediaRecorder.AudioSource.MIC
            }
            if(Build.VERSION.SDK_INT in 29..30){
                audioSource = MediaRecorder.AudioSource.VOICE_RECOGNITION
            }
            val audioEncoder = MediaRecorder.AudioEncoder.AAC

            val sampleDir = File("$dirPath/$dirName")

            if (!sampleDir.exists()) {
                sampleDir.mkdirs()
            }

//            val fileNameBuilder = StringBuilder()
//            fileNameBuilder.append(fileName)
//            fileNameBuilder.append("_")
//
//            if (showSeed) {
//                fileNameBuilder.append(seed)
//                fileNameBuilder.append("_")
//            }
//
//            if (showPhoneNumber && phoneNumber != null) {
//                fileNameBuilder.append(phoneNumber)
//                fileNameBuilder.append("_")
//            }

//            fileName = fileNameBuilder.toString()

            val suffix: String
            when (outputFormat) {
                MediaRecorder.OutputFormat.AMR_NB -> {
                    suffix = ".amr"
                }
                MediaRecorder.OutputFormat.AMR_WB -> {
                    suffix = ".amr"
                }
                MediaRecorder.OutputFormat.MPEG_4 -> {
                    suffix = ".mp3"
                }
                MediaRecorder.OutputFormat.THREE_GPP -> {
                    suffix = ".3gp"
                }
                else -> {
                    suffix = ".amr"
                }
            }

            audioFile =  File("$dirPath/$dirName/$fileName$suffix")
            audioFile!!.deleteOnExit()
            audioFile!!.createNewFile()
            recorder = MediaRecorder()
            recorder?.apply {
                setAudioSource(audioSource)
                setOutputFormat(outputFormat)
                setAudioEncoder(audioEncoder)
                setOutputFile(audioFile!!.absolutePath)
                setOnErrorListener { _, _, _ -> }
            }

            try {
                recorder?.prepare()
            } catch (e: IllegalStateException) {
                releaseMediaRecorder()
                return false
            } catch (e: IOException) {
                releaseMediaRecorder()
                return false
            }

            return true
        } catch (e: Exception) {
            e.printStackTrace()
            return false
        }
    }

    private fun releaseMediaRecorder() {
        recorder?.apply {
            reset()
            release()
        }
        recorder = null
    }
    companion object {
        //The receiver will be recreated whenever android feels like it.  We need a static variable to remember data between instantiations
        private var lastState = PhoneStateStatus.NOTHING;
        private var callStartTime: Date = Date()
        private var isIncoming: Boolean = false
        private var recorder: MediaRecorder? = null
    }


    private var audioFile: File? = null
    private var isRecordStarted = false
}